import 'dart:math' as math;
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import '../../core/constants.dart';
import 'puzzle_piece.dart';

/// 游戏状态模型
/// 
/// 设计思路：
/// 1. 单一数据源原则：所有游戏状态都在这个类中管理
/// 2. 计算属性：通过getter提供派生数据，避免冗余存储
/// 3. 状态机模式：明确的状态转换逻辑
class PuzzleGame extends Equatable {
  /// 拼图块列表
  final List<PuzzlePiece> pieces;
  
  /// 当前游戏状态
  final GameStatus status;
  
  /// 难度级别
  final DifficultyLevel difficulty;
  
  /// 当前使用的图片路径
  final String imagePath;

   final double imageAspectRatio; 
  
  /// 移动次数统计
  final int moveCount;
  
  /// 游戏开始时间
  final DateTime? startTime;
  
  /// 游戏结束时间
  final DateTime? endTime;
  
  /// 暂停总时长（V2.0功能预留）
  final Duration pausedDuration;
  
  /// 最佳记录（V2.0功能预留）
  final int? bestMoveCount;
  final Duration? bestTime;
  
  const PuzzleGame({
    required this.pieces,
    required this.status,
    required this.difficulty,
    required this.imagePath,
    this.moveCount = 0,
    this.startTime,
    this.endTime,
    this.imageAspectRatio = 1.0,
    this.pausedDuration = Duration.zero,
    this.bestMoveCount,
    this.bestTime,
  });
  
  /// 创建初始游戏状态
  factory PuzzleGame.initial() {
    return const PuzzleGame(
      pieces: [],
      status: GameStatus.initial,
      difficulty: DifficultyLevel.easy,
      imageAspectRatio: 1.0,
      imagePath: '',
    );
  }
  
  /// 创建加载中状态
  PuzzleGame toLoadingState() {
    return copyWith(status: GameStatus.loading);
  }
  
  /// 开始游戏
  PuzzleGame startGame() {
    return copyWith(
      status: GameStatus.playing,
      startTime: DateTime.now(),
      moveCount: 0,
    );
  }
  
  /// 完成游戏
  PuzzleGame completeGame() {
    return copyWith(
      status: GameStatus.completed,
      endTime: DateTime.now(),
    );
  }
  
  /// 暂停游戏
  PuzzleGame pauseGame() {
    return copyWith(status: GameStatus.paused);
  }
  
  /// 恢复游戏
  PuzzleGame resumeGame() {
    return copyWith(status: GameStatus.playing);
  }
  
  // =================== 计算属性 ===================
  
  /// 拼图块总数
  int get totalPieces => difficulty.totalPieces;
  
  /// 已正确放置的拼图块数量
  int get correctlyPlacedCount => 
      pieces.where((piece) => piece.isCorrectlyPlaced).length;
  
  /// 游戏完成度（0.0 - 1.0）
  double get completionPercentage {
    if (totalPieces == 0) return 0.0;
    return correctlyPlacedCount / totalPieces;
  }
  
  /// 是否游戏完成
  bool get isCompleted => correctlyPlacedCount == totalPieces;
  
  /// 是否游戏进行中
  bool get isPlaying => status == GameStatus.playing;
  
  /// 是否游戏暂停
  bool get isPaused => status == GameStatus.paused;
  
  /// 游戏已用时长
  Duration get elapsedTime {
    if (startTime == null) return Duration.zero;
    
    final endTimeOrNow = endTime ?? DateTime.now();
    final totalDuration = endTimeOrNow.difference(startTime!);
    
    return totalDuration - pausedDuration;
  }
  
  /// 游戏已用时长（格式化字符串）
  String get formattedElapsedTime {
    final duration = elapsedTime;
    final minutes = duration.inMinutes;
    final seconds = duration.inSeconds % 60;
    return '${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}';
  }
  
  /// 当前选中的拼图块
  PuzzlePiece? get selectedPiece => 
      pieces.where((piece) => piece.isSelected).firstOrNull;
  
  /// 获取指定位置的拼图块
  PuzzlePiece? getPieceAt(int row, int col) {
    return pieces
        .where((piece) => piece.currentRow == row && piece.currentCol == col)
        .firstOrNull;
  }
  
  /// 检查指定网格位置是否有拼图块（新增方法）
  bool isPositionOccupied(int row, int col) {
    return pieces.any((piece) => 
        piece.currentRow == row && piece.currentCol == col);
  }
  
  /// 获取指定ID的拼图块
  PuzzlePiece? getPieceById(int id) {
    return pieces.where((piece) => piece.id == id).firstOrNull;
  }
  
  /// 检查是否有拼图块在指定屏幕位置
  List<PuzzlePiece> getPiecesAtScreenPosition(Offset position) {
    return pieces.where((piece) => piece.bounds.contains(position)).toList();
  }
  
  /// 获取可移动的拼图块（未锁定且未正确放置）
  List<PuzzlePiece> get movablePieces => 
      pieces.where((piece) => !piece.isLocked && !piece.isPlaced).toList();
  
  /// 获取已放置的拼图块
  List<PuzzlePiece> get placedPieces => 
      pieces.where((piece) => piece.isPlaced).toList();
  
  /// 计算游戏评分（基于移动次数和时间）
  int get gameScore {
    if (!isCompleted) return 0;
    
    final timeBonus = math.max(0, 600 - elapsedTime.inSeconds); // 10分钟内完成有时间奖励
    final moveBonus = math.max(0, 1000 - moveCount * 10); // 移动次数越少奖励越多
    
    return timeBonus + moveBonus;
  }
  
  /// 游戏统计信息
  Map<String, dynamic> get gameStats => {
    'totalPieces': totalPieces,
    'placedPieces': correctlyPlacedCount,
    'completion': (completionPercentage * 100).toStringAsFixed(1),
    'moves': moveCount,
    'time': formattedElapsedTime,
    'score': gameScore,
  };
  
  // =================== 状态更新方法 ===================
  
  /// 更新拼图块
  PuzzleGame updatePiece(PuzzlePiece updatedPiece) {
    final updatedPieces = pieces.map((piece) {
      return piece.id == updatedPiece.id ? updatedPiece : piece;
    }).toList();
    
    return copyWith(pieces: updatedPieces);
  }
  
  /// 更新多个拼图块
  PuzzleGame updatePieces(List<PuzzlePiece> updatedPieces) {
    final pieceMap = {for (var piece in updatedPieces) piece.id: piece};
    
    final newPieces = pieces.map((piece) {
      return pieceMap[piece.id] ?? piece;
    }).toList();
    
    return copyWith(pieces: newPieces);
  }
  
  /// 增加移动次数
  PuzzleGame incrementMoveCount() {
    return copyWith(moveCount: moveCount + 1);
  }
  
  /// 选中拼图块
  PuzzleGame selectPiece(int pieceId) {
    final updatedPieces = pieces.map((piece) {
      return piece.copyWith(isSelected: piece.id == pieceId);
    }).toList();
    
    return copyWith(pieces: updatedPieces);
  }
  
  /// 清除所有选中状态
  PuzzleGame clearSelection() {
    final updatedPieces = pieces.map((piece) {
      return piece.copyWith(isSelected: false);
    }).toList();
    
    return copyWith(pieces: updatedPieces);
  }
  
  /// 打乱拼图块位置
  PuzzleGame shufflePieces() {
    final shuffledPieces = pieces.map((piece) {
      if (piece.isLocked) return piece; // 已锁定的拼图块不打乱
      
      return piece.copyWith(
        position: _generateRandomScatterPosition(),
        isPlaced: false,
        isSelected: false,
      );
    }).toList();
    
    return copyWith(
      pieces: shuffledPieces,
      moveCount: 0,
      startTime: DateTime.now(),
      status: GameStatus.playing,
    );
  }
  
  /// 生成随机散落位置
  Offset _generateRandomScatterPosition() {
    final random = math.Random();
    return Offset(
      AppConstants.defaultPadding.left + 
          random.nextDouble() * (300 - AppConstants.defaultPadding.horizontal),
      AppConstants.scatterAreaTop + 
          random.nextDouble() * AppConstants.scatterAreaHeight,
    );
  }
  
  /// 创建副本
  PuzzleGame copyWith({
    List<PuzzlePiece>? pieces,
    GameStatus? status,
    DifficultyLevel? difficulty,
    String? imagePath,
    double? imageAspectRatio, 
    int? moveCount,
    DateTime? startTime,
    DateTime? endTime,
    Duration? pausedDuration,
    int? bestMoveCount,
    Duration? bestTime,
  }) {
    return PuzzleGame(
      pieces: pieces ?? this.pieces,
      status: status ?? this.status,
      difficulty: difficulty ?? this.difficulty,
      imagePath: imagePath ?? this.imagePath,
      imageAspectRatio: imageAspectRatio ?? this.imageAspectRatio,
      moveCount: moveCount ?? this.moveCount,
      startTime: startTime ?? this.startTime,
      endTime: endTime ?? this.endTime,
      pausedDuration: pausedDuration ?? this.pausedDuration,
      bestMoveCount: bestMoveCount ?? this.bestMoveCount,
      bestTime: bestTime ?? this.bestTime,
    );
  }
  
  @override
  List<Object?> get props => [
    pieces,
    status,
    difficulty,
    imagePath,
    imageAspectRatio,
    moveCount,
    startTime,
    endTime,
    pausedDuration,
  ];
  
  @override
  String toString() => 'PuzzleGame('
      'status: $status, '
      'difficulty: $difficulty, '
      'pieces: ${pieces.length}, '
      'placed: $correctlyPlacedCount/$totalPieces, '
      'moves: $moveCount)';
}

/// 游戏状态扩展方法
extension PuzzleGameExtensions on PuzzleGame {
  /// 是否可以开始游戏
  bool get canStart => 
      status == GameStatus.initial && pieces.isNotEmpty && imagePath.isNotEmpty;
  
  /// 是否可以暂停游戏
  bool get canPause => status == GameStatus.playing;
  
  /// 是否可以恢复游戏
  bool get canResume => status == GameStatus.paused;
  
  /// 是否可以重置游戏
  bool get canReset => status != GameStatus.initial && status != GameStatus.loading;
  
  /// 获取游戏难度颜色
  Color get difficultyColor => difficulty.color;
  
  /// 获取游戏状态显示文本
  String get statusDisplayText => status.displayName;
}
